package com.zmn.oms.dubbo.impl.zmn.normal.erp;

import com.google.common.collect.Lists;
import com.zmn.common.constant.GlobalConsts;
import com.zmn.common.utils.reflect.BeanMapper;
import com.zmn.oms.business.interfaces.es.OrderWorkEsBService;
import com.zmn.oms.common.constant.OrderConsts;
import com.zmn.oms.dubbo.dto.zmn.erp.OmsErpOrderDRO;
import com.zmn.oms.dubbo.dto.zmn.erp.OmsErpOrderDiscountDRO;
import com.zmn.oms.dubbo.dto.zmn.erp.OmsErpOrderIdDIO;
import com.zmn.oms.dubbo.dto.zmn.erp.OmsErpOrderPayDRO;
import com.zmn.oms.dubbo.interfaces.zmn.normal.erp.ZsNormalErpRemoteService;
import com.zmn.oms.dubbo.utils.DubboConsts;
import com.zmn.oms.model.entity.discount.OrderDiscount;
import com.zmn.oms.model.entity.invoice.OrderInvoice;
import com.zmn.oms.model.entity.pay.OrderPay;
import com.zmn.oms.model.entity.work.OrderWork;
import com.zmn.base.oms.common.model.es.orderwork.EsOrderWork;
import com.zmn.oms.services.interfaces.detail.OrderDetailService;
import com.zmn.oms.services.interfaces.discount.OrderDiscountService;
import com.zmn.oms.services.interfaces.invoice.OrderInvoiceService;
import com.zmn.oms.services.interfaces.pay.OrderPayService;
import com.zmn.oms.services.interfaces.work.OrderWorkService;
import com.zmn.oms.services.interfaces.work.financework.FinanceWorkService;
import com.zmn.oms.zmn.normal.business.interfaces.work.financework.ZsNormalFinanceWorkBService;
import com.zmn.pay.common.constant.PayConsts;
import org.apache.dubbo.config.annotation.Service;
import org.elasticsearch.index.query.BoolQueryBuilder;
import org.elasticsearch.index.query.QueryBuilders;
import org.elasticsearch.index.query.RangeQueryBuilder;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Sort;
import org.springframework.data.elasticsearch.core.SearchHit;
import org.springframework.data.elasticsearch.core.SearchHits;
import org.springframework.data.elasticsearch.core.query.FetchSourceFilter;
import org.springframework.data.elasticsearch.core.query.NativeSearchQuery;
import org.springframework.data.elasticsearch.core.query.SourceFilter;
import org.springframework.util.CollectionUtils;

import java.util.ArrayList;
import java.util.List;
import java.util.Objects;
import java.util.stream.Collectors;

/**
 * 类描述：啄木鸟取数
 *
 * @author heciqi
 * @date 2019/08/07 9:50
 */
@Service(loadbalance = "roundrobin", timeout = 5000, retries = 2, version = DubboConsts.INTERFACE_VERSION, validation = "false")
public class ZsNormalErpRemoteServiceImpl implements ZsNormalErpRemoteService {
	private Logger logger = LoggerFactory.getLogger(ZsNormalErpRemoteServiceImpl.class);

	@Autowired
	OrderWorkService orderWorkService;
	@Autowired
	OrderDetailService orderDetailService;
	@Autowired
	OrderWorkEsBService orderWorkEsBService;
	@Autowired
	OrderDiscountService orderDiscountService;
	@Autowired
	OrderInvoiceService orderInvoiceService;
	@Autowired
	ZsNormalFinanceWorkBService zsNormalFinanceWorkBService;
	@Autowired
	OrderPayService orderPayService;
	@Autowired
	protected FinanceWorkService financeWorkService;

	/**
	 * 在工单上获取ERP相关数据
	 * 时间跨度在一天内分时段数据，es有查询条数10000限制。
	 * 例子:开始时间：2019-08-06 10:00:00 结束时间：2019-08-06 14:00:00
	 *
	 * @param accStartTime 算账开始时间
	 * @param accEndTime   算账结束时间
	 * @return
	 */
	@Override
	public List<OmsErpOrderDRO> listErpDRO(Integer plat, String accStartTime, String accEndTime) {
		BoolQueryBuilder builder = QueryBuilders.boolQuery();
		RangeQueryBuilder queryBuilder = QueryBuilders.rangeQuery("accountTime");
		queryBuilder.gte(accStartTime);
		queryBuilder.lte(accEndTime);
		builder.must(queryBuilder);
		if (plat != null) {
			builder.filter(QueryBuilders.termQuery("platWork", plat));
		}
		NativeSearchQuery searchQuery = new NativeSearchQuery(builder);
		searchQuery.setPageable(PageRequest.of(0, 10000, Sort.by(Sort.Order.asc("accountTime"))));
		// 只显示的字段
		String[] includes = {"id", "orderId", "companyId", "factoryOrder", "channelId", "type", "bizType",
				"receiveTime", "cityId", "provinceId", "countyId", "hasInvoice", "originalAmount", "discountAmount", "servCategId",
				"servCategId", "categOneId", "categTwoId", "productId", "productGroupId", "masterId", "masterName", "userId", "platWork",
				"plat", "sourceType", "payStatus", "partAmount", "reWorkId"
		};
		SourceFilter sourceFilter = new FetchSourceFilter(includes, new String[]{});
		searchQuery.addSourceFilter(sourceFilter);

		List<EsOrderWork> esOrderWorks = orderWorkEsBService.listPageByQuery(searchQuery);
		if (CollectionUtils.isEmpty(esOrderWorks)) {
			return Lists.newArrayList();
		}

		List<OmsErpOrderDRO> retList = new ArrayList<>();
		esOrderWorks.forEach(esOrderWork -> {
			logger.debug("es实体[{}]",esOrderWork.toString());
			// 工单信息设置
			OmsErpOrderDRO erpOrderDRO = BeanMapper.map(esOrderWork, OmsErpOrderDRO.class);
			erpOrderDRO.setWorkId(esOrderWork.getId());
			erpOrderDRO.setProvinceId(esOrderWork.getProvinceId());
			erpOrderDRO.setDistrictId(esOrderWork.getCountyId());
			erpOrderDRO.setReciveTime(esOrderWork.getReceiveTime());
			erpOrderDRO.setBizType(esOrderWork.getBizType());
			erpOrderDRO.setCategId(esOrderWork.getCategTwoId());
			if (esOrderWork.getContact() != null) {
				erpOrderDRO.setUserName(esOrderWork.getContact().getUserName());
				if (esOrderWork.getContact().getPhone() != null) {// 取第一个手机号
					erpOrderDRO.setUserTel(esOrderWork.getContact().getPhone()[0]);
				}
			}
			erpOrderDRO.setOrderCityId(esOrderWork.getCityId());

			// 厂商id
			if (Objects.equals(esOrderWork.getSourceType(), OrderConsts.ORDER_SOURCE_TYPE_FACTORY)) {
				if (esOrderWork.getFactoryOrder() != null) {
					erpOrderDRO.setFactoryId(esOrderWork.getFactoryOrder().getFactoryId());
				}
			}

			// 返修单源工程师
			logger.debug("返修单源工程师");
			//Integer sourceMasterId = null;
			if (Objects.equals(esOrderWork.getType(), OrderConsts.ORDER_TYPE_REWORK)) {
				OrderWork reworkOrderWork = orderWorkService.findOrderWorkByKey(esOrderWork.getReworkId(), esOrderWork.getReworkId());
				erpOrderDRO.setSourceMasterId(reworkOrderWork != null ? reworkOrderWork.getMasterId() : null);
				erpOrderDRO.setSourceMasterName(reworkOrderWork != null ? reworkOrderWork.getMasterName() : null);
			}

			// 优惠券
			logger.debug("优惠券");
			if (!CollectionUtils.isEmpty(esOrderWork.getDiscountList())) {
				List<OrderDiscount> orderDiscounts = orderDiscountService.listByOrderId(esOrderWork.getOrderId());
				erpOrderDRO.setDiscountList(BeanMapper.mapList(orderDiscounts, OmsErpOrderDiscountDRO.class));
			}

			// 发票
			logger.debug("发票");
			if (esOrderWork.getHasInvoice() != null && esOrderWork.getHasInvoice()) {
				OrderInvoice orderInvoice = orderInvoiceService.findOrderInvoiceByKey(esOrderWork.getOrderId());
				if (orderInvoice != null) {
					erpOrderDRO.setInvoiced(true);
					erpOrderDRO.setTitle(orderInvoice.getTitle());
					erpOrderDRO.setNumber(orderInvoice.getNumber());
					erpOrderDRO.setBillAmount(orderInvoice.getAmount());
					erpOrderDRO.setBillCompanyId(orderInvoice.getCompanyId());
				} else {
					erpOrderDRO.setBillAmount(null);
				}
			}

			// 支付凭证
			logger.debug("支付凭证");
			List<OrderPay> orderPays = orderPayService.listOrderPayByOrderIdAndWorkId(esOrderWork.getOrderId(), esOrderWork.getId());
			if (!CollectionUtils.isEmpty(orderPays)) {
				List<OmsErpOrderPayDRO> erpOrderPayDROS = BeanMapper.mapList(orderPays, OmsErpOrderPayDRO.class);
				erpOrderPayDROS.forEach(e -> {
					if (Objects.equals(e.getDuplicate(), GlobalConsts.YES)) {
						logger.info("重复支付不算入erp算账");
						return;
					}
					e.setPayChannelName(PayConsts.getPayChannelName(e.getPayChannelId()));
					e.setUnionPay(Objects.equals(e.getPayChannelId(), PayConsts.PAY_CHANNEL_THIRD_CHINAUMS) ? GlobalConsts.YES : GlobalConsts.NO);
					e.setPreGetType(GlobalConsts.NO);
				});
				erpOrderDRO.setOrderPayList(erpOrderPayDROS);
			}
			logger.debug("ERP实体[{}]",erpOrderDRO);
			retList.add(erpOrderDRO);
		});

		logger.info("本次调用数据返回数[{}]",retList.size());
		return retList;
	}

	/**
	 * 在工单上获取ERP相关数据
	 * @param list
	 * @return
	 */
	@Override
	public List<OmsErpOrderDRO> listErpDRO(List<OmsErpOrderIdDIO> list) {
		return null;
	}

}
